/******************************************************************************
 * FileName:    gwin_remote.c
 * Desc:        遥控
 *
 *
 * Author:      Lin
 * Notes:
 *
 ******************************************************************************/

/*-------------------------- Includes ---------------------------------------*/
#include "gwin_board.h"
#include "gwin_remote.h"
#include "gwin_main_task.h"

#include "gwin_remote_gwin.h"

#include "gwin_remote_leshi.h"
#include "gwin_remote_pingtouxiong.h"

/*-------------------------- Macro Definitions ------------------------------*/
#define LOCAL_DEBUG_EN                      ( 0 )
#if LOCAL_DEBUG_EN
#define GWIN_DEBUG(...)                     USER_DEBUG(__VA_ARGS__)
#else
#define GWIN_DEBUG(...)
#endif


#define GWIN_REMOTE_DATA_LEN_MIN            ( 2 + 16 )
#define GWIN_REMOTE_FILTER_MAX_CNT          ( 10 )
#define GWIN_REMOTE_FILTER_TIMEOUT          ( 10 )
#define GWIN_REMOTE_ACTION_MAX_CNT          ( 10 )


/*-------------------------- Type Declarations ------------------------------*/
/**
 * @brief 广播包解析缓存
 */
typedef struct
{
    uint8_t data[GWIN_REMOTE_ACTION_MAX_CNT];               // 数据
    uint8_t in  : 4;                                        // 写
    uint8_t out : 4;                                        // 读
}remote_action_map_t;


/*-------------------------- Global Variables -------------------------------*/

/*-------------------------- Local Variables --------------------------------*//**
 * @brief 多协议解析处理表
 */
static const gwin_remote_date_proc_map_t gwin_remote_date_proc_map[] =
{
    { .gwin_remote_date_check_func = gwin_remote_date_check_gwin,           .gwin_remote_date_proc_func = gwin_remote_date_proc_gwin        },
    { .gwin_remote_date_check_func = gwin_remote_date_check_leshi,          .gwin_remote_date_proc_func = gwin_remote_date_proc_leshi           },
    { .gwin_remote_date_check_func = gwin_remote_date_check_pingtouxiong,   .gwin_remote_date_proc_func = gwin_remote_date_proc_pingtouxiong    },
};
static const uint8_t gwin_remote_date_proc_map_cnt = ARRAY_NUM(gwin_remote_date_proc_map);

static remote_filter_map_t remote_filter_map[GWIN_REMOTE_FILTER_MAX_CNT] = { 0x00 };
static uint8_t remote_filter_map_cnt = 0;
static remote_action_map_t remote_action_map;


/*-------------------------- Functions Declarations -------------------------*/

/*-------------------------- Functions Definitions --------------------------*/
/**
 * @brief 使能打开接收广播
 *          协议栈初始化完成再调用
 */
void gwin_remote_scan_start(void)
{
    memset(remote_filter_map, 0x00, sizeof(remote_filter_map));
    memset(&remote_action_map, 0x00, sizeof(remote_action_map));
}


/**
 * @brief 遥控过滤同一遥控同一指令
 */
static uint8_t gwin_remote_filter(remote_pair_info_t *remote_pair_info, uint8_t cmd_id)
{
    // 数组满则删除旧值
    #define ARRAY_CHECK_DEL_OLD_DATA(arr, cnt)                                                              \
                                                        if (cnt == ARRAY_NUM(arr))                          \
                                                        {                                                   \
                                                            memcpy(&arr[0], &arr[1], ARRAY_NUM(arr) - 1);   \
                                                            cnt = ARRAY_NUM(arr) - 1;                       \
                                                        }


    uint8_t match_remote_id = INVALID_U8;
    uint8_t match_cmd_id = 0;

    // 清理超时值
    for (uint8_t i = 0; i < remote_filter_map_cnt;)
    {
        if (gwin_pass_general_clock(remote_filter_map[i].hold_clock, GWIN_REMOTE_FILTER_TIMEOUT * 1000))
        {
            if (i == (remote_filter_map_cnt - 1))
            {
                memset(&remote_filter_map[remote_filter_map_cnt - 1], 0x00, sizeof(remote_filter_map_t));
            }
            else
            {
                memcpy(&remote_filter_map[i], &remote_filter_map[i + 1], sizeof(remote_filter_map_t) * (remote_filter_map_cnt - (i + 1)));
            }
            remote_filter_map_cnt--;
        }
        else
        {
            i++;
        }
    }

    // 匹配过滤值
    for (uint8_t i = 0; i < remote_filter_map_cnt; i++)
    {
        if (memcmp(remote_pair_info->remote_id, remote_filter_map[i].remote_id, sizeof(remote_pair_info->remote_id)) == 0)
        {
            match_remote_id = i;
            for (uint8_t j = 0; j < remote_filter_map[match_remote_id].cmd_cnt; j++)
            {
                if (cmd_id == remote_filter_map[match_remote_id].cmd_id[j])
                {
                    match_cmd_id = 1;
                    break;
                }
            }
            break;
        }
    }

    // 添加到过滤表
    if (match_remote_id != INVALID_U8)  // 遥控存在
    {
        if (!match_cmd_id)              // 命令id不存在，添加命令id
        {
            ARRAY_CHECK_DEL_OLD_DATA(remote_filter_map[match_remote_id].cmd_id, remote_filter_map[match_remote_id].cmd_cnt);
            remote_filter_map[match_remote_id].cmd_id[remote_filter_map[match_remote_id].cmd_cnt] = cmd_id;
            remote_filter_map[match_remote_id].cmd_cnt++;
        }
    }
    else                                // 遥控不存在
    {
        ARRAY_CHECK_DEL_OLD_DATA(remote_filter_map, remote_filter_map_cnt);
        // 添加到记录表中
        match_remote_id = remote_filter_map_cnt;
        remote_filter_map_cnt++;
        memset(&remote_filter_map[match_remote_id], 0x00, sizeof(remote_filter_map_t));
        memcpy(remote_filter_map[match_remote_id].remote_id, remote_pair_info->remote_id, sizeof(remote_pair_info->remote_id));
        remote_filter_map[match_remote_id].cmd_id[remote_filter_map[match_remote_id].cmd_cnt] = cmd_id;
        remote_filter_map[match_remote_id].cmd_cnt++;
    }
    gwin_save_general_clock(&remote_filter_map[match_remote_id].hold_clock);

    return (match_cmd_id > 0);
}



/**
 * @brief 遥控接收数据
 */
void gwin_remote_date_recv(uint8_t *data, uint16_t len)
{
    if (len < GWIN_REMOTE_DATA_LEN_MIN) return;

    remote_pair_info_t remote_pair_info = { 0x00 };
    uint8_t adv_payload_pos = 0;
    uint8_t cmd_index = 0;
    uint8_t action = 0;
    uint32_t param = 0;

    for (uint8_t i = 0; i < gwin_remote_date_proc_map_cnt; i++)
    {
        if (gwin_remote_date_proc_map[i].gwin_remote_date_check_func(data, len, &remote_pair_info, &adv_payload_pos, &cmd_index) >= 0)
        {
            // 过滤同一遥控同一指令
            if (!gwin_remote_filter(&remote_pair_info, cmd_index))
            {
                gwin_remote_date_proc_map[i].gwin_remote_date_proc_func(&data[adv_payload_pos], len - adv_payload_pos, &remote_pair_info, &action, &param);
                GWIN_DEBUG("action = %d, param = %d", action, param);
                if (action > 0)
                {
                    // LIN MARK 230609 : 小米SDK技术支持建议：接收广播数据是SDK回调，多任务，只做数据解析，不做动作，动作放在while(1)处理
                    remote_action_map.data[remote_action_map.in] = action;
                    remote_action_map.in++;
                    remote_action_map.in %= GWIN_REMOTE_ACTION_MAX_CNT;
                    if (remote_action_map.in == remote_action_map.out)
                    {
                        remote_action_map.out++;
                        remote_action_map.out %= GWIN_REMOTE_ACTION_MAX_CNT;
                    }

                    GWIN_DEBUG("remote recv action = %d, out = %d, in = %d", action, remote_action_map.out, remote_action_map.in);
                }
            }
            break;
        }
    }
}

/**
 * @brief 任务
 *          处理数据
 */
void gwin_remote_task(void)
{
    if (remote_action_map.out != remote_action_map.in)
    {
        uint8_t action = remote_action_map.data[remote_action_map.out];
        remote_action_map.out++;
        remote_action_map.out %= GWIN_REMOTE_ACTION_MAX_CNT;

        GWIN_DEBUG("remote task do action = %d, out = %d, in = %d", action, remote_action_map.out, remote_action_map.in);

        switch (action)
        {
            default:
                gwin_main_extern_action(action);
                break;
        }
    }
}


/*-------------------------- END OF FILE ------------------------------------*/

